/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is Forte for Java, Community Edition. The Initial
* Developer of the Original Code is Sun Microsystems, Inc. Portions
* Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.modules.web.core.jsploader;
import java.io.IOException;
import java.io.File;
import org.openide.compiler.Compiler;
import org.openide.compiler.CompilerJob;
import org.openide.compiler.CompilerTask;
import org.openide.compiler.CompilerGroup;
import org.openide.compiler.CompilerType;
import org.openide.compiler.ErrorEvent;
import org.openide.compiler.ProgressEvent;
import org.openide.cookies.CompilerCookie;
import org.openide.cookies.SaveCookie;
import org.openide.execution.NbProcessDescriptor;
import org.openide.execution.NbClassPath;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.FileSystem;
import org.openide.filesystems.FileStateInvalidException;
import org.openide.loaders.CompilerSupport;
import org.openide.loaders.DataObject;
import org.openide.loaders.MultiDataObject;
import org.openide.loaders.MultiDataObject.Entry;
import org.openide.util.NbBundle;
import com.sun.jsp.JspException;
import com.sun.jsp.compiler.ParseException;
import com.sun.jsp.compiler.JspReader;
import com.sun.jsp.compiler.Main;
import org.netbeans.modules.java.JCompilerSupport;
import org.netbeans.modules.java.JavaDataObject;
import org.netbeans.modules.java.JavaCompilerType;
/** JSP compiler
*
* @author Petr Jiricka
*/
public class JspCompiler extends Compiler {
/** copy of type */
private Class type;
protected final JspDataObject jspdo;
protected boolean errorPage;
private Main.ClassFileData cfd;
JavaCompilerType.IndirectCompiler servletCompiler;
boolean successful = false;
/** Constant for compilation. */
public static final Class COMPILE = CompilerCookie.Compile.class;
/** Constant for building. */
public static final Class BUILD = CompilerCookie.Build.class;
/** Constant for clean. */
public static final Class CLEAN = CompilerCookie.Clean.class;
public JspCompiler(JspDataObject jspdo, Class type) {
super();
if (type == CLEAN)
this.type = BUILD;
else
this.type = type;
if ((this.type != COMPILE) && (this.type != BUILD))
throw new IllegalArgumentException();
this.jspdo = jspdo;
}
public JspDataObject getDataObject() {
return jspdo;
}
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public void setErrorPage(boolean errorPage) {
this.errorPage = errorPage;
}
public boolean isErrorPage() {
return errorPage;
}
/**
*/
public Class compilerGroupClass() {
return Group.class;
}
/** Checks if the class corresponding to this JSP is up to date
*/
public boolean isUpToDate() {
if (type == BUILD) return false;
return jspdo.isUpToDate();
}
/** See {@link Compilable#equals(java.lang.Object)}
*/
public boolean equals (Object other) {
if (!(other instanceof JspCompiler))
return false;
JspCompiler comp2 = (JspCompiler)other;
boolean eq = (comp2.jspdo == jspdo); // && (comp2.errorPage == errorPage));
return eq;
}
public int hashCode () {
return ((jspdo == null) ? 0 : jspdo.hashCode());
}
/** Identifier for type of compiler. This method allows subclasses to specify
* the type this compiler belongs to. Compilers that belong to the same class
* will be compiled together by one external process.
* <P>
* It is necessary for all compilers of the same type to have same process
* descriptor and error expression.
* <P>
* This implementation returns the process descriptor, so all compilers
* with the same descriptor will be compiled at once.
*
* @return key to define type of the compiler (file object representing root of filesystem)
* or null if there are any errors
* @see ExternalCompilerGroup#createProcess
*/
public Object compilerGroupKey () {
return jspdo;
}
void setClassFileData(Main.ClassFileData cfd) {
this.cfd = cfd;
}
Main.ClassFileData getClassFileData() {
return cfd;
}
public String toString() {
String result = "JspCompiler: " + jspdo.getPrimaryFile().getPackageNameExt('/','.') + // NOI18N
", errorPage: " + errorPage + " "; // NOI18N
if (type == BUILD)
result = result + "BUILD";
if (type == COMPILE)
result = result + "COMPILE";
return result;
}
void setToServletCompiler(FileObject fo) {
if (servletCompiler == null) return;
servletCompiler.setResolved(fo);
}
/** Compiler group for servlet code generation. */
public static class Group extends CompilerGroup {
public Group() {
super();
}
private JspCompiler comp;
public void add(Compiler c) throws IllegalArgumentException {
if (!(c instanceof JspCompiler))
throw new IllegalArgumentException();
if (comp != null)
throw new IllegalArgumentException();
comp = ((JspCompiler)c);
}
public boolean start() {
try {
// prepare the file and class names
comp.getDataObject().updateClassFileData();
Main.ClassFileData cfd = JspCompileUtil.cloneClassFileData(
comp.getDataObject().getClassFileData());
cfd.incrementNumber();
comp.setClassFileData(cfd);
String outputDir = getOutputDir(comp.getDataObject());
JspReader reader = JspReader.createJspReader(JspCompileUtil.getFileObjectFileName(
comp.getDataObject().getPrimaryFile()));
try {
// generate the servlet source
fireProgressEvent(new ProgressEvent(this, comp.getDataObject().getPrimaryFile(),
ProgressEvent.TASK_GENERATING));
JspCompileUtil.generate(reader, comp.getDataObject().getPrimaryFile(),
outputDir, cfd, comp.isErrorPage()
);
comp.getDataObject().servletGenerated();
JspServletDataObject servlet = comp.getDataObject().getServletDataObject();
if (servlet == null) {
fireErrorEvent(new ErrorEvent(this, comp.getDataObject().getPrimaryFile(),
-1, -1, NbBundle.getBundle(JspCompiler.class).getString("CTL_ServletNotFound"), ""));
return false;
}
// compile the servlet
fireProgressEvent(new ProgressEvent(this, servlet.getPrimaryFile(),
ProgressEvent.TASK_GENERATING));
comp.setToServletCompiler(servlet.getPrimaryFile());
comp.successful = true;
return true;
}
catch (JspException e) {
// thrown in the first phase - delete the generated erroneous servlet
deleteErroneousServletCatch(cfd);
comp.getDataObject().servletGenerated();
fireErrorEvent(ErrorCompiler.Group.constructError(
this, e, comp.getDataObject().getPrimaryFile(), false));
return false;
}
catch (NoClassDefFoundError e) {
// thrown in the first phase - delete the generated erroneous servlet
deleteErroneousServletCatch(cfd);
comp.getDataObject().servletGenerated();
fireErrorEvent(new ErrorEvent(this, comp.getDataObject().getPrimaryFile(),
-1, -1, e.getMessage(), ""));
return false;
}
}
catch (ThreadDeath e) {
throw e;
}
catch (Throwable e) {
fireErrorEvent(ErrorCompiler.Group.constructError(
this, e, comp.getDataObject().getPrimaryFile(), true));
return false;
}
}
/** Returns the actual output directory for servlets generated from a given JSP page
* (not a root of the hierarchy). */
static String getOutputDir(DataObject jspdo) throws IOException {
File jspFile = new File(JspCompileUtil.getFileObjectFileName(jspdo.getPrimaryFile()));
String folderName = Main.getPackageName(jspFile).replace('.','/');
FileObject fsRoot = JspCompileUtil.getContextOutputRoot(jspdo.getPrimaryFile());
FileObject packageFolder = fsRoot.getFileSystem().find(folderName, null, null);
if (packageFolder == null) {
packageFolder = FileUtil.createFolder(fsRoot, folderName);
}
return JspCompileUtil.getFileObjectFileName(packageFolder);
}
private void deleteErroneousServletCatch(Main.ClassFileData cfd) {
try {
deleteErroneousServlet(cfd);
}
catch (IOException ioe) {
// not a bad error
if (Boolean.getBoolean("netbeans.debug.exceptions")) // NOI18N
ioe.printStackTrace();
}
}
private void deleteErroneousServlet(Main.ClassFileData cfd) throws IOException {
File jspFile = new File(JspCompileUtil.getFileObjectFileName(comp.getDataObject().getPrimaryFile()));
jspFile.getPath();
FileObject contextOutputRoot = JspCompileUtil.getContextOutputRoot(comp.getDataObject().getPrimaryFile());
String pkg = Main.getPackageName(jspFile);
FileObject fileDir = contextOutputRoot.getFileSystem().find(pkg, null, null);
fileDir.refresh();
FileObject servletFo;
String almostFileName = JspCompileUtil.getClassNameSansNumberSansPackage(
comp.getDataObject().getPrimaryFile());
servletFo = fileDir.getFileObject(almostFileName + cfd.getNumber(), "java"); // NOI18N
/* File ff = NbClassPath.toFile(servletFo);
if (ff != null)
if (ff.exists()) {
if (!ff.delete())
throw new IOException();
}*/
if (servletFo != null) {
FileLock lock = servletFo.lock();
try {
servletFo.delete(lock);
}
finally {
lock.releaseLock();
}
}
}
} // end of inner class Group
}
/*
* Log
* 32 Gandalf 1.31 1/27/00 Petr Jiricka Changes in generating
* names of the servlet
* 31 Gandalf 1.30 1/17/00 Petr Jiricka Debug outputs removed
* 30 Gandalf 1.29 1/16/00 Petr Jiricka Duplicate checks etc.
* 29 Gandalf 1.28 1/15/00 Petr Jiricka More fixes.
* 28 Gandalf 1.27 1/15/00 Petr Jiricka Ensuring correct
* compiler implementation - hashCode and equals
* 27 Gandalf 1.26 1/14/00 Petr Jiricka Compilation fixes
* 26 Gandalf 1.25 1/13/00 Petr Jiricka Bugfix 5331
* 25 Gandalf 1.24 1/12/00 Petr Jiricka Fully I18n-ed
* 24 Gandalf 1.23 1/12/00 Petr Jiricka i18n phase 1
* 23 Gandalf 1.22 1/10/00 Petr Jiricka Significant compilation
* change - prepare compilers for Java beforehand.
* 22 Gandalf 1.21 1/7/00 Petr Jiricka Cleanup
* 21 Gandalf 1.20 1/7/00 Petr Jiricka
* 20 Gandalf 1.19 1/6/00 Petr Jiricka Cleanup
* 19 Gandalf 1.18 1/4/00 Petr Jiricka Fixed minor bug
* 18 Gandalf 1.17 1/4/00 Petr Jiricka
* 17 Gandalf 1.16 1/4/00 Petr Jiricka More bugfixes
* 16 Gandalf 1.15 1/3/00 Petr Jiricka Changes in deleting the
* servlet
* 15 Gandalf 1.14 1/3/00 Petr Jiricka Bugfixes
* 14 Gandalf 1.13 12/29/99 Petr Jiricka Various compilation
* fixes
* 13 Gandalf 1.12 12/28/99 Petr Jiricka Reflectiong compilation
* API changes
* 12 Gandalf 1.11 12/20/99 Petr Jiricka Checking in changes made
* in the U.S.
* 11 Gandalf 1.10 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun
* Microsystems Copyright in File Comment
* 10 Gandalf 1.9 10/12/99 Petr Jiricka Removed debug messages
* 9 Gandalf 1.8 10/12/99 Petr Jiricka defaultCompilerType
* fixed
* 8 Gandalf 1.7 10/12/99 Petr Jiricka Fixed bug with default
* compiler type
* 7 Gandalf 1.6 10/10/99 Petr Jiricka Servlet package change
* 6 Gandalf 1.5 10/10/99 Petr Jiricka Changed compilation
* style EternalCompilerSettings -> CompilerType
* 5 Gandalf 1.4 10/4/99 Petr Jiricka
* 4 Gandalf 1.3 9/29/99 Petr Jiricka Compilation fixes -
* consecutive names
* 3 Gandalf 1.2 9/27/99 Petr Jiricka Added compilation of the
* resulting servlet
* 2 Gandalf 1.1 9/22/99 Petr Jiricka Improved compilation
* error reporting.
* 1 Gandalf 1.0 9/22/99 Petr Jiricka
* $
*/